﻿using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using TmU220PrintHelperV2d0.Entity;
using ZhangLogSysV1d0;

namespace EscPrinterHelperV1d0.Service
{
    /// <summary>
    /// 传输数据给打印机，通过套接字
    /// </summary>
    public class TransferDataToPrinterV1d0:ITransferDataToPrinter
    {
        /// <summary>
        /// 发送文本,需要将文本编码转换为打印机字库编码，然后再将转换后的字符串（打印机字库编码）转换为字节数组，发送给打印机
        /// </summary>
        /// <param name="content">待发送文本</param>
        /// <param name="encodingNameOfContent">文本的自身编码</param>
        /// <param name="encodingNameOfPrinter">打印机的字库编码</param>
        /// <param name="printerTcpClient">打印机套接字</param>
        /// <returns>是否发送成功</returns>
        public bool SendText(string content, bool isTraditionalOfContent, bool isTraditionalOfPrinter, TcpClient printerTcpClient)
        {
            bool isSuccess = false;
            try
            {
                //转换内容的简繁体转换为打印机的简繁体
                string contentOfPrinterEncoding = SimplifiedAndTraditionalTransform(content, isTraditionalOfContent, isTraditionalOfPrinter);
                //将字符串转换为打印机字库编码的字节数组
                Encoding printerEncoding = Encoding.GetEncoding(contentOfPrinterEncoding);
                byte[] bytes = printerEncoding.GetBytes(content);
                isSuccess = SendBytes(bytes, printerTcpClient);
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
                isSuccess = false;
            }
            return isSuccess;
        }
        /// <summary>
        /// 发送图片
        /// </summary>
        public bool SendImage(Bitmap bitmap, TcpClient printerTcpClient)
        {
            bool isSuccess = false;
            try
            {
                bool isCorrect = CheckBitmapFormat(bitmap);
                if (isCorrect == false) return false;
                else
                {
                    int bitmapHeight = bitmap.Height;
                    int rowCount = bitmapHeight / 8;//行高度8个像素
                    for (int i = 0; i < rowCount; i++)
                    {
                        //将行位图（高度8个像素）发送到打印机
                        SendScanLineOfBitmapToPrinter(bitmap,i, printerTcpClient);
                        //15个打印机垂直运动单位
                        byte TMU220B_VerticalMoveUnits = 15;
                        //打印机走纸15个垂直运动单位
                        SendBytes(PrinterEscCommandConstantV2d0.printAndFeedPaper_VerticalUnit(TMU220B_VerticalMoveUnits), printerTcpClient);
                    }
                    return true;
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
            return isSuccess;
        }
        /// <summary>
        /// 对于TMU220打印，每次只能打印8像素高度的图像，将高度为8像素，宽度为图像宽度的矩形区域部分称为一个8点扫描行
        /// 如果图像高度为24个像素，则该图像有3个8点扫描行
        /// 发送位图的一个8点扫描行到打印机
        /// </summary>
        /// <param name="rowIndex">8点扫描行的行序号</param>
        /// <param name="bitmap">待打印位图</param>
        private void SendScanLineOfBitmapToPrinter(Bitmap bitmap,int rowIndex, TcpClient printerTcpClient)
        {
            bool isCorrect = CheckBitmapFormat(bitmap);
            try
            {
                if (isCorrect)
                {
                    //将位图指定行转换成,打印机的位图字节数组,双密度打印
                    byte[] bitmapByteArray = GetBytesOfScanLine(bitmap, rowIndex);
                    SendBytes(bitmapByteArray, printerTcpClient);
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
        }
        /// <summary>
        /// 发送字节数组
        /// </summary>
        public bool SendBytes(byte[] bytes, TcpClient printerTcpClient)
        {
            bool isSuccess = false;
            try
            {
                if (printerTcpClient != null && printerTcpClient.Connected)
                {
                    NetworkStream netStream = printerTcpClient.GetStream();
                    netStream.Write(bytes, 0, bytes.Length);
                    netStream.Flush();
                    isSuccess = true;
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
                isSuccess = false;
            }
            return isSuccess;
        }
        /// <summary>
        ///将打印数据的简繁体编码，转换为打印机的简繁体编码 
        ///简繁体处理，主打印数据是简体还是繁体，打印机是简体还是繁体
        /// </summary>
        /// <param name="printTask"></param>
        /// <param name="isTraditinalOfPrinter"></param>
        public static string SimplifiedAndTraditionalTransform(string sourceText,bool isTraditonalOfSource,bool isTraditionalOfTarget)
        {
            string resultString = string.Empty;
            //繁体-简体 需要转换
            if (isTraditonalOfSource && (!isTraditionalOfTarget))
            {
                resultString = ChineseConverter.Convert(sourceText, ChineseConversionDirection.TraditionalToSimplified);
            }
            //简体-繁体 需要转换
            else if (isTraditonalOfSource && (isTraditionalOfTarget))
            {
                resultString = ChineseConverter.Convert(sourceText, ChineseConversionDirection.SimplifiedToTraditional);
            }
            //简体-简体  繁体-繁体 无需转换
            else    {
                resultString = sourceText;
            }
            return resultString;
        }
        /// <summary>
        /// 对位图格式进行检查，宽度必须400像素，高度必须是8的整数倍
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static bool CheckBitmapFormat(Bitmap bitmap)
        {
            bool result = false;
            try
            {
                if (bitmap != null)
                {
                    int width = bitmap.Width;
                    int height = bitmap.Height;
                    if (width != 400) result = false;
                    else result = true;
                    if (height % 8 != 0) result = false;
                    else result = true;
                }
            }
            catch (Exception ex)
            {
                SimpleLoger.Instance.Error(ex);
            }
            return result;
        }
        /// <summary>
        /// 得到图像扫描行的字节数组(用于发送给打印机)
        /// 8点双密度,打印针垂直有8根针，每根针对应一个像素点。一行可以最多打印400像素宽的图像
        /// tm-u220圖形打印模式是8點双密度
        /// 位图的宽和高，宽度固定为400，高度应为8的整数倍
        /// </summary>
        /// <param name="printBitmap">待打印位图</param>
        /// <param name="scanLineIndex">8像素扫描线序号，8像素高度为一条水平扫描线，第几条薯片扫描线，从0开始</param>
        /// <returns></returns>
        public static byte[] GetBytesOfScanLine(Bitmap printBitmap, int scanLineIndex)
        {
            //最多256列，最多4行，每個字節表示8個像素
            //tm-u220圖形打印模式是點單双密度
            int heightPixels = printBitmap.Height;
            int widthPixels = printBitmap.Width;
            byte nL = (byte)(widthPixels - 256);//一个存储行,最多256列.对于400列的位图需要分成两行存储（如果图像宽度没有超过256像素，则nH=0）
            byte nH = 1;//只有8个针，故一次只能打印一个扫描行，如果有24根针，一次就可以打印4行（最多一次打印4行）
            int dataByteArraySize = nL + nH * 256 + 5;//总数据个数
            byte[] bytesOfAll = new byte[dataByteArraySize];
            //填充图像模式头 5个字节
            FillBytesHeaderOfImageModeBytes(printBitmap, ref bytesOfAll);
            if ((scanLineIndex + 1) * 8 > heightPixels) return bytesOfAll;
            else
            {
                FillBytesContentOfImageModeBytes(printBitmap, scanLineIndex, ref bytesOfAll);
            }
            return bytesOfAll;
        }

        /// <summary>
        /// 填充图像模式下图像数据的内容字节数组
        /// </summary>
        /// <param name="printBitmap">待打印图像</param>
        /// <param name="scanLineIndex">扫描线序号</param>
        /// <param name="bytesOfAll">待填充的字节数组</param>
        public static void FillBytesContentOfImageModeBytes(Bitmap printBitmap,int scanLineIndex,ref byte[] bytesOfAll)
        {
            int widthPixels = printBitmap.Width;
            for (int i = 0; i < widthPixels; i++)
            {
                for (int j = scanLineIndex; j < scanLineIndex + 1; j++)
                {
                    if (i < widthPixels)
                    {
                        //每个字节仅保存 0或者1
                        byte[] bitArray = new byte[8];
                        for (int n = 0; n < 8; n++)
                        {
                            byte b = 0;
                            //自下而上 8个像素（每个像素只有黑白两色）组合成一个字节
                            Color pixel = printBitmap.GetPixel(i, j * 8 + 7 - n);
                            b = Color2BlackWhite(pixel);
                            bitArray[n] = b;
                        }
                        bytesOfAll[i + 5] = (byte)ChangeBitArray2Int(bitArray);
                    }
                }
            }
        }
        /// <summary>
        /// 得到图像模式下图像数据的头字节数组（图像宽度400像素）
        /// </summary>
        /// <param name="printBitmap">待打印图像</param>
        /// <returns>头字节数组</returns>
        public static void FillBytesHeaderOfImageModeBytes(Bitmap printBitmap, ref byte[] bytesOfAll)
        {
            //tm-u220圖形打印模式是點單双密度
            int heightPixels = printBitmap.Height;
            int widthPixels = printBitmap.Width;
            byte nL = (byte)(widthPixels - 256);//一个存储行,最多256列.对于400列的位图需要分成两行存储（如果图像宽度没有超过256像素，则nH=0）
            byte nH = 1;//只有8个针，故一次只能打印一个扫描行，如果有24根针，一次就可以打印4行（最多一次打印4行）
            bytesOfAll[0] = 0x1B;
            bytesOfAll[1] = 0x2A;
            //m=1 8点双密度默认边距条件下,可以打印像素宽度为400以内的图片
            bytesOfAll[2] = 1;
            bytesOfAll[3] = nL;
            bytesOfAll[4] = nH;
        }
        /// <summary>
        /// 图片二值化，黑色是1，白色是0 核心方法
        /// </summary>
        /// <param name="pixel">像素点颜色</param>
        /// <returns>黑或者白</returns>
        public static byte Color2BlackWhite(Color pixel)
        {
            byte b;
            int gray = RGB2Gray(pixel.R, pixel.G, pixel.B);
            b = (byte)(gray < 128 ? 1 : 0);
            return b;
        }

        /// <summary>
        /// 将[1,0,0,1,0,0,0,1]这样的二进制转为化十进制的数值（效率更高）,核心方法
        /// </summary>
        /// <param name="arry"></param>
        /// <returns></returns>
        public static int ChangeBitArray2Int(byte[] arry)
        {
            int v = 0;
            for (int j = 0; j < arry.Length; j++)
            {
                if (arry[j] == 1)
                {
                    v = v | 1 << j;
                }
            }
            return v;
        }
       

        /// <summary>
        /// 图片灰度的转化 核心方法
        /// </summary>
        /// <param name="r"></param>
        /// <param name="g"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        private static int RGB2Gray(int r, int g, int b)
        {
            int gray = (int)(0.29900 * r + 0.58700 * g + 0.11400 * b);  //灰度转化公式
            return gray;
        }
        /// <summary>
        /// 根据图像宽度，对文本进行分行，并计算文本块的高度
        /// </summary>
        /// <param name="text">待分行文本</param>
        /// <param name="textFont">文本显示 字体</param>
        /// <param name="bitmapWidth">图像宽度</param>
        /// <param name="bitmapHeight">待计算图像高度</param>
        /// <returns>已分行文本</returns>
        public static string TextWrap(string text,Font textFont,int bitmapWidth,out float bitmapHeight)
        {
            bitmapHeight = 0;
            StringBuilder wrapedTextSBuilder = new StringBuilder();
            StringBuilder contentBuilder = new StringBuilder();
            Bitmap printBitmap = new Bitmap(bitmapWidth, 32); 
            Graphics canvasGraphics = Graphics.FromImage(printBitmap);
            string initString = contentBuilder.ToString();
            StringBuilder widthCheckBuilder = new StringBuilder();
            foreach (char item in text)
            {
                widthCheckBuilder.Append(item);
                string widthCheckString = widthCheckBuilder.ToString();
                //测量字符串宽度，高度
                SizeF contentSizeF = canvasGraphics.MeasureString(widthCheckString, textFont);
                if(contentSizeF.Width>bitmapWidth)
                {
                    wrapedTextSBuilder.Append(Environment.NewLine);
                    widthCheckBuilder.Clear();
                }
                wrapedTextSBuilder.Append(item);
            }
            string wrapedText= wrapedTextSBuilder.ToString();
            SizeF wrapedTextSizeF= canvasGraphics.MeasureString(wrapedText, textFont);
            bitmapHeight = wrapedTextSizeF.Height;
            return wrapedText;
        }
        public static Bitmap DrawTextToBitmap(string text, Font textFont, int bitmapWidth)
        {
            float bitmapHeight = 0;
            string textForDraw = TextWrap(text, textFont, bitmapWidth,out bitmapHeight);
            //图像的高度必须为8的整数倍
            bitmapHeight = (float) Math.Ceiling(bitmapHeight / 8) *8;
            Bitmap resultBitmap = new Bitmap(bitmapWidth, (int)bitmapHeight);
            Graphics  canvasGraphics= Graphics.FromImage(resultBitmap);
            SolidBrush myBrush = new SolidBrush(Color.Black);
            canvasGraphics.DrawString(textForDraw, textFont, myBrush, 0, 0);
            myBrush.Dispose();
            myBrush = null;
            canvasGraphics.Dispose();
            canvasGraphics = null;
            return resultBitmap;
        }
    }
}
